package com.teufandsub.socialproximity.gui;

import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Locale;

import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;

import com.teufandsub.socialproximity.R;
import com.teufandsub.socialproximity.controller.Constants;
import com.teufandsub.socialproximity.controller.Controller;
import com.teufandsub.socialproximity.controller.Utils;
import com.teufandsub.socialproximity.logic.Interest;
import com.teufandsub.socialproximity.logic.MultipleChoiceSpinner;
import com.teufandsub.socialproximity.logic.MultipleChoiceSpinner.MultiSpinnerListener;
import com.teufandsub.socialproximity.logic.RegistrationInfo;
import com.teufandsub.socialproximity.logic.User;

/**
 * @author Bastien Mathias <bastienmathias@gmail.com>
 * @author Antoine Teuf <antoine.teuf@gmail.com>
 * @version 1.0
 * @since 2013-05-22
 * 
 * Activity to change personnal settings, add/remove interests.
 */

public class SettingsActivity extends SocialProxActivity implements MultiSpinnerListener,
																OnClickListener{

	private ArrayList<Interest> linkedInterests, unLinkedInterests;
	private ArrayList<Interest> addingInterestsAl, deletingInterestsAl;
	private MultipleChoiceSpinner addingInterest,deletingInterest;
	private RadioGroup sexRg;
	private RadioButton maleRb,femaleRb,unknownRb,nameShowRb,nameDontShowRb;
	private User currentUser;
	private EditText mailEt,passwdEt,confPasswdEt;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_settings);
		controller = Controller.getInstance();
		addingInterestsAl=new ArrayList<Interest>();
		deletingInterestsAl=new ArrayList<Interest>();
		
		addingInterest = (MultipleChoiceSpinner) findViewById(R.id.adding_interest_spinner);
		deletingInterest = (MultipleChoiceSpinner) findViewById(R.id.deleting_interest_spinner);
		
		mailEt = (EditText) findViewById(R.id.email_et);
		passwdEt = (EditText) findViewById(R.id.password_et);
		confPasswdEt = (EditText) findViewById(R.id.conf_password_et);
		
		Button addButton = (Button) findViewById(R.id.adding_button);
		addButton.setOnClickListener(this);
		
		Button deletingButton = (Button) findViewById(R.id.deleting_button);
		deletingButton.setOnClickListener(this);
		
		Button modifyButton = (Button) findViewById(R.id.modifyButton);
		modifyButton.setOnClickListener(this);
		
		sexRg = (RadioGroup) findViewById(R.id.radio_group_gender);
		maleRb = (RadioButton) findViewById(R.id.gender_male);
		femaleRb = (RadioButton) findViewById(R.id.gender_female);
		unknownRb = (RadioButton) findViewById(R.id.gender_dont_show);
		
		nameShowRb = (RadioButton) findViewById(R.id.name_show);
		nameDontShowRb = (RadioButton) findViewById(R.id.name_dont_show);
		
	}

	@Override
	protected void onResume() {
		super.onResume();
		
		SimpleEntry<String,JSONObject> prefs = controller.getSessionInfo(this);
		try {
			currentUser = new User(prefs.getValue());
		} catch (Exception e) {
			Log.e(Constants.APP_NAME, "Error to set informations from preferences : " + e.toString());
		}
		
		switch(currentUser.getSex()){
			case User.SEX_MALE : 
				maleRb.setChecked(true);
				break;
			case User.SEX_FEMALE : 
				femaleRb.setChecked(true);
				break;
			case User.SEX_UNKNOWN :
				unknownRb.setChecked(true);
				break;
		}
		
		if(currentUser.showRealName()){
			nameShowRb.setChecked(true);
		}else{
			nameDontShowRb.setChecked(true);
		}
		mailEt.setText(currentUser.getEmail());
		
		if(Utils.hasConnectivity(this)){
			linkedInterests = toList(getInterests(true));
			unLinkedInterests = toList(getInterests(false));
		}else{
			Log.i(Constants.APP_NAME, "Error to connect...");
			Toast.makeText(this, getResources().getString(R.string.no_connectivity)
					, Toast.LENGTH_LONG).show();
			linkedInterests = new ArrayList<Interest>();
			unLinkedInterests = new ArrayList<Interest>();
		}
		
		ArrayList<String> unLinkedInt = toStringList(unLinkedInterests);
		ArrayList<String> linkedInt = toStringList(linkedInterests);

		addingInterest.setItems(unLinkedInt,"", this);
		deletingInterest.setItems(linkedInt,"", this);
	}
	
	@Override
	public void onItemsSelected(boolean[] selected, int id) {
		switch(id){
		case R.id.adding_interest_spinner:
			for(int i=0; i<selected.length;i++){
				if(selected[i]==true){
					addingInterestsAl.add(unLinkedInterests.get(i));
				}		
			}
			break;
		case R.id.deleting_interest_spinner:
			for(int i=0; i<selected.length;i++){
				if(selected[i]==true){
					deletingInterestsAl.add(linkedInterests.get(i));
				}		
			}
			break;
		}
	};
	
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.adding_button:
			setAction(Constants.ADDINTERESTLINK, addingInterestsAl);
			break;
		case R.id.deleting_button:
			setAction(Constants.REMOVEINTERESTLINK, deletingInterestsAl);
			break;
		case R.id.modifyButton:
		
			int sex;
			switch (sexRg.getCheckedRadioButtonId()) {
				case R.id.gender_male:
					sex = RegistrationInfo.SEX_MALE;
					break;
				case R.id.gender_female:
					sex = RegistrationInfo.SEX_FEMALE;
					break;
				case R.id.gender_dont_show:
					sex = RegistrationInfo.SEX_UNKNOWN;
					break;
				default:
					sex = User.SEX_UNKNOWN;
			}
			
			//Update sex
			currentUser.setSex(sex);
			
			//Update mail
			if (!mailEt.getText().toString().isEmpty() && Utils.validateEmail(mailEt.getText().toString())) {
				currentUser.setEmail(mailEt.getText().toString());
			}
			
			//Update showRealName
			if(nameShowRb.isChecked()){
				currentUser.setShowRealName(true);
			}else{
				currentUser.setShowRealName(false);
			}
			
			//Update to the cloud
			AsyncTask<Void, Void, JSONObject> task = new AsyncTask<Void, Void, JSONObject>(){
				private Dialog dialog;
				@Override
				protected void onPreExecute() {
					super.onPreExecute();
					dialog = ProgressDialog.show(SettingsActivity.this, "", getResources().getString(R.string.loading), true);
				}
				
				protected JSONObject doInBackground(Void... params) {
					return controller.updateUserInformations(SettingsActivity.this,currentUser.toJSONObject());
				}
				
				@Override
				protected void onPostExecute(JSONObject result) {
					super.onPostExecute(result);
					int code = Constants.CODE_ERROR;
					try {
						code = result.getInt(Constants.CODE_NAME);
					} catch (Exception e) {
						Log.e(Constants.APP_NAME, "Error to manage friend : " + e.toString());
					}
					switch(code){
						case Constants.CODE_ERROR:
							Toast.makeText(SettingsActivity.this, SettingsActivity.this.getResources().getString(R.string.error)
									, Toast.LENGTH_LONG).show();
							break;
						case Constants.CODE_REQUESTVALID:
							//Update session Info
							Toast.makeText(SettingsActivity.this, SettingsActivity.this.getResources().getString(R.string.update)
									, Toast.LENGTH_LONG).show();
							SimpleEntry<String,JSONObject> prefs = controller.getSessionInfo(SettingsActivity.this);
							controller.initSessionId(SettingsActivity.this, prefs.getKey(), currentUser.toJSONObject());
							break;
					}
					passwdEt.setText("");
					confPasswdEt.setText("");
					dialog.dismiss();
				}
			};
			if(passwdEt.getText().toString().equals(confPasswdEt.getText().toString())){
				if(!passwdEt.getText().toString().isEmpty()){
					currentUser.setPassword(Utils.toMD5(passwdEt.getText().toString()));
				}
				
				if(Utils.hasConnectivity(this)){
					Log.e(Constants.APP_NAME, "Task calling");
					task.execute();
				}else{
					Log.e(Constants.APP_NAME, "No Task calling");
					Toast.makeText(this, this.getResources().getString(R.string.no_connectivity), Toast.LENGTH_LONG).show();
				}
			}else{
				Toast.makeText(this, getResources().getString(R.string.different_passwd), Toast.LENGTH_LONG).show();
			}
			
			break;
		}
		
	}
	
	/**
	 * Method to get interests from the cloud application.
	 * 
	 * @param isLinked boolean value to know which if we want to retrieve linked interests or not.
	 * @return {@link JSONObject} list of interests as an JSONObject
	 */
	public JSONObject getInterests(final boolean isLinked) {
		AsyncTask<Void,Void,JSONObject> task = new AsyncTask<Void, Void, JSONObject>() {

			@Override
			protected JSONObject doInBackground(Void... params) {
				if(isLinked){
					return controller.getLinkedInterests(SettingsActivity.this,
							currentUser.getUsername());
				}else{
					return controller.getUnlinkedInterests(SettingsActivity.this,
							currentUser.getUsername());
				}
			}
			
			protected void onPostExecute(JSONObject result) {
				int code = Constants.CODE_ERROR;
				try {
					code = result.getInt(Constants.CODE_NAME);
				} catch (Exception e) {
					Log.e(Constants.APP_NAME, "Error to manage friend : " + e.toString());
				}
				
				if(code==Constants.CODE_ERROR){
					Intent i = new Intent(SettingsActivity.this, HomeActivity.class);
					startActivity(i);
					Toast.makeText(SettingsActivity.this, SettingsActivity.this.getResources().getString(R.string.error)
							, Toast.LENGTH_LONG).show();
				}
			};
			
		}.execute();
		
		JSONObject returnValue = null;
		try {
			returnValue = task.get();
		} catch (Exception e) {
		}
		return returnValue;		
	}
	
	/**
	 * Method used to convert a list of Interest as an JSONObject to an ArrayList
	 * 
	 * @param result JSONObject list of Interest as an JSONObject
	 * @return ArrayList<Interest> list of Interest as an Arraylist.
	 */
	public ArrayList<Interest> toList(JSONObject result){
		ArrayList<Interest> interestsAl = new ArrayList<Interest>();
		int code = Constants.CODE_ERROR;
		try {
			code = result.getInt(Constants.CODE_NAME);
		} catch (Exception e) {
			Log.e(Constants.APP_NAME,
					"Error to retrieve code from interests request "
							+ e.toString());
		}

		switch (code) {
		case Constants.CODE_ERROR:
			Toast.makeText(SettingsActivity.this,
					getResources().getString(R.string.get_users_error),
					Toast.LENGTH_LONG).show();
			break;

		case Constants.CODE_REQUESTVALID:
			JSONArray interests = new JSONArray();
			try {
				interests = result
						.getJSONArray(Constants.INTERESTLIST_NAME);
			} catch (Exception e) {
				Log.e(Constants.APP_NAME,
						"Error to retrieve interest to JSONArray"
								+ e.toString());
			}

			for (int i = 0; i < interests.length(); i++) {
				try {
					interestsAl.add(new Interest(interests.getJSONObject(i)));
				} catch (Exception e) {
					Log.e(Constants.APP_NAME,
							"Error to convert JsonArray<Interest> to Arraylist<Interest> ");
				}
			}
		}
		return interestsAl;
	}
	
	/**
	 * Method used to convert and ArrayList of Interest to a list of String.
	 * 
	 * @param interests ArrayList<Interest> the list of Interest
	 * @return ArrayList<String> The list of string representation of interests.
	 */
	public ArrayList<String> toStringList(ArrayList<Interest> interests){
		ArrayList<String> returnValue = new ArrayList<String>();
		if(Locale.getDefault().getLanguage().contains("fr")){
			for (Interest interest : interests) returnValue.add(interest.getFrenchName());
		}else{
			for (Interest interest : interests) returnValue.add(interest.getEnglishName());
		}
		return returnValue;
	}
	
	/**
	 * Method used to set the action to do with the specific list of interest.
	 * 
	 * @param action int The action to do on click.
	 * @param inters ArrayList<Interest> list of interests to the action.
	 */
	public void setAction(final int action, final ArrayList<Interest> inters){
		AsyncTask<Void, Void, JSONObject> task = new AsyncTask<Void, Void, JSONObject>() {
			private Dialog dialog;
			@Override
			protected void onPreExecute() {
				super.onPreExecute();
				dialog = ProgressDialog.show(SettingsActivity.this, "", getResources().getString(R.string.loading), true);
			}
			
			@Override
			protected JSONObject doInBackground(Void... params) {
				JSONObject info = new JSONObject();
				JSONArray interestsJSONArray = new JSONArray();
				
				for(Interest  inter : inters){
					interestsJSONArray.put(inter.getName());
				}
				
				try {
					info.put(Constants.ACTIONCODE_NAME, action);
					info.put(Constants.TARGETNAMESLINK_NAME,interestsJSONArray);
				} catch (Exception e) {
					Log.e(Constants.APP_NAME, "Error to set update informations : " + e.toString());
				}
				return controller.manageInterests(SettingsActivity.this, info);
			}
			
			protected void onPostExecute(JSONObject result) {
				int code = Constants.CODE_ERROR;
				try {
					code = result.getInt(Constants.CODE_NAME);
				} catch (Exception e) {
					Log.e(Constants.APP_NAME, "Error to manage friend : " + e.toString());
				}
				
				switch(code){
					case Constants.CODE_REQUESTVALID:
						Toast.makeText(SettingsActivity.this, SettingsActivity.this.getResources().getString(R.string.update)
								, Toast.LENGTH_LONG).show();
						
						linkedInterests = toList(getInterests(true));
						unLinkedInterests = toList(getInterests(false));
						
						ArrayList<String> unLinkedInt = toStringList(unLinkedInterests);
						ArrayList<String> linkedInt = toStringList(linkedInterests);

						addingInterest.setItems(unLinkedInt,"", SettingsActivity.this);
						deletingInterest.setItems(linkedInt,"", SettingsActivity.this);
						
						break;
						
					case Constants.CODE_ERROR:
						Toast.makeText(SettingsActivity.this, SettingsActivity.this.getResources().getString(R.string.error)
								, Toast.LENGTH_LONG).show();
						break;

				}		
				dialog.dismiss();
			};
		};
		
		if(Utils.hasConnectivity(this)){
			task.execute();
		}else{
			Toast.makeText(this, this.getResources().getString(R.string.no_connectivity), Toast.LENGTH_LONG).show();
		}
	}
}
